<?php
// +----------------------------------------------------------------------
// | Author: July
// +----------------------------------------------------------------------
// | 创建时间: 2023-12-27 20:39:42
// +----------------------------------------------------------------------
// | 后台菜单控制器
// +----------------------------------------------------------------------


namespace july\julyadmin\admin\controller;

use july\julyadmin\builder\traits\HasBuilder;
use july\julyadmin\common\logic\MenuLogic;
use july\julyadmin\common\model\Menu as MenuModel;

class Menu extends Common
{
    use HasBuilder;

    //不需要登录验证的控制器和方法，如：['index']
    protected $noNeedLogin = [];
    //不需要权限验证的控制器和方法，如：['index']
    protected $noPermissionAuth = [];

    public function __construct()
    {
        //重新初始化父类
        parent::initialize();
        //数据模型
        $this->dataModel = new MenuModel();
        //join关联查询的表信息如，['category'=>'inner','comment'=>'left']
        $this->relationWithJoins = ['parentmenu' => 'left'];
        //with预查询关联表信息，如category,comment
        $this->relationWiths = [];
        //页面标题
        $this->pageTitle = '菜单管理';
        //允许表格行内编辑的字段,如name,sex
        $this->allowRowEditField = ['name', 'disabled', 'is_top_left', 'is_top_right','sort'];
        //不允许删除的主键数组，如1,2,3
        $this->noDeletePrimarykeys = [];
        //不允许编辑的主键数组，如1,2,3
        $this->noEditPrimarykeys = [];
        //不允许禁用的主键数组，如1,2,3
        $this->noDisabledPrimarykeys = [];
        //下拉join关联查询的表信息如，['category'=>'inner','comment'=>'left']
        $this->selectRelationWithJoins = [];
        //下拉with预查询关联表信息，如category,comment
        $this->selectRelationWiths = [];
        //下拉列表默认查询条件，如 [['disabled', '=', 1]]，如果有配置了$this->selectRelationWithJoins，这里就需要注意了，排序字段需要带上表名加一个点，如admin.
        $this->selectWhere = [];
        //下拉列表模糊查询字段,如 'name|title'，如果有配置了$this->selectRelationWithJoins，这里就需要注意了，排序字段需要带上表名加一个点，如admin，当前表可以不加
        $this->selectSearch = 'name';
        //下拉列表默认 Text 字段 如 '{id}#{nickname}'或者'id:{id}-名称:{name}'，如果有配置了$this->selectRelationWithJoins，这里就需要注意了，排序字段需要带上表名加一个点，如admin，当前表可以不加
        $this->selectTextField = '{id}#{name}';
        //下拉默认id字段,如：id
        $this->selectIdField = 'id';
        //下拉列表查询时的字段，如：id,name，如果有配置了$this->selectRelationWithJoins，这里就需要注意了，排序字段需要带上表名加一个点，如admin.，当前表可以不加
        $this->selectFields = 'id,name';
        //下拉列表父id字段，如：parent_id，如果有配置了$this->selectRelationWithJoins，这里就需要注意了，排序字段需要带上表名加一个点，如admin.
        $this->selectParentId = 'parent_id';
        //下拉列表查询第一层数据列表条件，如[['parent_id','=',0]],当表格为treeTable的时候，意味着你要输出的数据也会是树形的，这个时候首次查询最父层的数据列表可能需要传入这个参数，如果有配置了$this->SelectRelationWithJoins，这里就需要注意了，排序字段需要带上表名加一个点，如admin.
        $this->selectOneParentWhere = [];
        //下拉列表查询排序，如果有配置了$this->selectRelationWithJoins，这里就需要注意了，排序字段需要带上表名加一个点，如admin.
        $this->selectOrder = 'sort ASC';
        //列表排序，如果有配置了$this->relationWithJoins，这里就需要注意了，排序字段需要带上表名加一个点，如admin.
        $this->sort = 'menu.id desc';
        //父id字段名称，如parent_id,当表格为treeTable的时候，意味着你要输出的数据也会是树形的，这个时候需要指定父级字段名称，如果有配置了$this->selectRelationWithJoins，这里就需要注意了，排序字段需要带上表名加一个点，如admin.，根据实际需求修改
        $this->parentField = 'menu.parent_id';
        //查询第一层数据列表条件，如[['parent_id','=',0]],当表格为treeTable的时候，意味着你要输出的数据也会是树形的，这个时候首次查询最父层的数据列表可能需要传入这个参数，如果有配置了$this->relationWithJoins，这里就需要注意了，排序字段需要带上表名加一个点，如admin.
        $this->oneParentWhere = [['menu.parent_id', '=', 0]];
        //表格类型,table,treeTable
        $this->tableType = 'treeTable';
        //树形表格分组字段，比如name，那么展开和搜索箭头就会在name这一列显示，当表格为treeTable的时候会用到
        $this->treeTableGroupField = 'name';
        //需要合计的字段，如['显示在哪个字段','显示哪个字段的值']，如果有配置了$this->selectRelationWithJoins，这里就需要注意了，排序字段需要带上表名加一个点，如['id'=>'admin.sex','money'=>admin.money']
        $this->totalRow = [];
        //设置主键
        $this->pk = 'id';
    }

    /**
     * 设置当前页面
     * @Author   July
     * @DateTime 2024-01-13T19:41:56+0800
     * @param    $table 表格
     */
    protected function buildPage(&$table = [])
    {
        //搜索
        $table->getSearch()
            ->show('text', 'name', '菜单名称')->placeholder('菜单名称');

        //表格工具栏
        $table->getToolbar()
            ->addBtn()
            ->disabledBtn()
            ->deleteBtn()
            ->refreshBtn();

        //表格数据
        $table->showCheckbox();
        $table->show('id', 'ID')->sort(true)->width(100);
        $table->show('name', '菜单名称')->width(200)->sort(true);
        $table->show('plugin_id', '插件ID')->width(200)->sort(true);
        $table->show('plugin_name', '插件名称')->width(200)->sort(true);
        $table->show('controller', '控制器')->width(200)->sort(true);
        $table->show('action', '方法')->width(200)->sort(true);
        $table->show('is_top_left', '是否顶部左边菜单', 'switchBtn')->width(200)->switchBtnText(['是', '否'])->edit('switchBtn')->sort(true);
        $table->show('is_top_right', '是否顶部右边菜单', 'switchBtn')->width(200)->switchBtnText(['是', '否'])->edit('switchBtn')->sort(true);
        $table->show('ico', '图标')->align('center')->width(100)->templet("return '<i class=\"'+val+'\"></i>';")->sort(true);
        $table->show('disabled', '禁用状态', 'switchBtn')->edit('switchBtn')->sort(true)->width(120)->sort(true);
        $table->show('sort', '排序')->edit('number')->sort(true)->width(120)->sort(true);
        $table->show('create_time', '创建时间')->width(170)->sort(true);
        $table->show('update_time', '更新时间')->width(170)->sort(true);

        //表格右侧操作列
        $table->showRowHandleMenus()->width(130);
        $table->getTableRowBtns()
            ->editBtn()
            ->viewBtn()
            ->deleteBtn();

    }

    /**
     * 处理数据
     * 因为查询出来的数据可能需要二次处理
     * @Author   July
     * @DateTime 2024-01-13T19:44:46+0800
     * @param  array   &$data 查询出来的数据
     */
    protected function handleData(&$data = [])
    {

    }

    /**
     * 处理查询条件
     * @Author   July
     * @DateTime 2023-11-16T20:45:54+0800
     * @param array $search  查询条件
     * @return  array $where
     */
    protected function filterWhere($search = [])
    {
        $where = [];
        foreach ($search as $k => $v) {
            if ($v === "") {
                continue;
            }
            switch ($k) {
                case "id":
                    $where[] = ['menu.id', '=', $v];
                    break;
                case "name":
                    $where[] = ['menu.name', 'like', '%' . $v . '%'];
                    break;
                case "disabled":
                    $where[] = ['menu.disabled', '=', $v];
                    break;
            }
        }

        return $where;
    }

    /**
     * 处理下拉列表查询条件
     * @Author   July
     * @DateTime 2024-01-13T19:47:05+0800
     * @param  array $where  现有的查询条件
     * @return array
     */
    protected function filterSelectPageWhere($where = [])
    {

        return $where;
    }

    /**
     * 处理合计行信息
     * @Author   July
     * @DateTime 2023-11-16T20:45:54+0800
     * @param    array                   $where    已经处理过的最终查询条件，可以自己覆盖，用来自己重新查询数据
     * @param    integer                 $limit    每页多少条
     * @param    string                  $sort     排序
     * @param    integer                 $page     第几页
     * @param    array                   $totalRow 已经查询出来的合计信息，可以自己覆盖返回
     * @return   array                   $totalRow 将处理过的最终信息返回
     */
    protected function filterTotalRow($where = [], $limit = 20, $sort = '', $page = 1, $totalRow = [])
    {
        return $totalRow;
    }

    /**
     * @Author   July
     * @DateTime 2024-01-13T19:49:03+0800
     * @param    Object                   &$form  form对象
     * @param    integer                  $isEdit 是否是编辑：0否，1是
     * @param    array                    &$data  当前这条数据的内容
     */
    protected function buildForm(&$form, $isEdit, &$data = [])
    {
        $permissions = (new MenuLogic($this))->getPermissionsSelect();
        if ($isEdit) {
            $data['url'] = "{$data['module']}\\{$data['controller']}\\{$data['action']}";
        }

        $form->show('text', 'name', '菜单名称')->required();
        $form->show('select', 'parent_id', '上级菜单')->dataUrl(url("Menu/selectPage"))->help('不选择就是一级菜单');
        $form->show('select', 'url', 'url')->options($permissions)->help('如果下级还有菜单，那么这里不能选，否则会导致角色权限出问题。');
        $form->show('iconPicker', 'ico', '图标');
        $form->show('number', 'sort', '排序')->default(0)->help('越小越靠前');
        $form->show('checkbox', 'attrs', '属性')->options(['is_top_left' => '左上角菜单', 'is_top_right' => '右上角菜单']);
        $form->show('switchBtn', 'disabled', '禁用状态')->default(1);
        if ($isEdit) {
            $attrs = [];
            if ($data['is_top_left']) {
                $attrs[] = 'is_top_left';
            }
            if ($data['is_top_right']) {
                $attrs[] = 'is_top_right';
            }

            $data['attrs'] = implode(',', $attrs);
            $form->show('html', 'create_time', '创建时间');
            $form->show('html', 'update_time', '更新时间');
        }
    }

    /**
     * 保存
     * @Author   July
     * @DateTime 2023-11-16T20:45:54+0800
     * @param  integer $isEdit 是否是编辑 0否，1是
     */
    protected function save($isEdit)
    {
        $pk = input("get." . $this->getPk());

        $data = request()->only([
            'name',
            'parent_id',
            'ico',
            'disabled',
            'url',
            'sort',
            'attrs',
        ], 'post');

        try {
            validate([
                'name|菜单名称' => 'require',
                'sort|排序'   => 'require|number',
            ])->check($data);
        } catch (\think\exception\ValidateException $e) {
            $this->error($e->getError());
        }

        if (!isset($data['parent_id'])) {
            $data['parent_id'] = 0;
        }

        $data['is_top_left']  = isset($data['attrs']) && in_array('is_top_left', $data['attrs']) ? 1 : 0;
        $data['is_top_right'] = isset($data['attrs']) && in_array('is_top_right', $data['attrs']) ? 1 : 0;
        if (isset($data['attrs'])) {
            unset($data['attrs']);
        }

        if (isset($data['url']) && $data['url']) {
            //解析路由
            $routerPreg = '~([a-zA-Z0-9]+)\\\([a-zA-Z0-9]+)\\\([a-zA-Z0-9]+)~';
            preg_match_all($routerPreg, $data['url'], $res);
            $module     = isset($res[1][0]) ? $res[1][0] : '';
            $controller = isset($res[2][0]) ? $res[2][0] : '';
            $action     = isset($res[3][0]) ? $res[3][0] : '';

            $data['module']     = $module;
            $data['controller'] = $controller;
            $data['action']     = $action;
        } else {
            $data['module']     = '';
            $data['controller'] = '';
            $data['action']     = '';
        }

        return $this->doSave($isEdit, $data, $pk);
    }
}
